home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Basic Source Code
/
Visual Basic Source Code.iso
/
vbsource
/
rpcdcpro
/
server.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-09-09
|
10KB
|
260 lines
//-----------------------------------------------------------------------------
// This program illustrates a simple server implementation
// The server is listening on the tcp and udp ports
//-----------------------------------------------------------------------------
#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <math.h>
#include <rpcdc.h>
//-----------------------------------------------------------------------------
// Here is a definition of a structure that must be transmitted to the server
// One possibility is to develop a specific XDR function, used with transmit/
// receive functions
//-----------------------------------------------------------------------------
typedef struct _TEST {
int i1;
int i2;
int i3;
float f;
double d;
} TEST;
//-----------------------------------------------------------------------------
// First write the XDR function - standard structure
// The parameters are as follows :
// h : (void *) points to the host binary representation of the data
// n : (void *) points to the network binary representation of the data
// code : indicates the operation to perform (3 possibilities)
// --> XDR_ENCODE : conversion h -> n
// --> XDR_DECODE : conversion n -> h
// --> XDR_MEMORY : just returns the size of the object
//-----------------------------------------------------------------------------
size_t _xdr_TEST (void *h, void *n, int code)
{
TEST *hi=(TEST *)h; // first convert pointers
char *ni=(char *)n;
size_t size;
switch (code) {
case XDR_ENCODE:
case XDR_DECODE:
size=_xdr_int(NULL,NULL,XDR_MEMORY);
_xdr_int((void *)&hi->i1,(void *)ni,code); ni+=size;
_xdr_int((void *)&hi->i2,(void *)ni,code); ni+=size;
_xdr_int((void *)&hi->i3,(void *)ni,code); ni+=size;
size=_xdr_float(NULL,NULL,XDR_MEMORY);
_xdr_float((void *)&hi->f,(void *)ni,code); ni+=size;
size=_xdr_double(NULL,NULL,XDR_MEMORY);
_xdr_double((void *)&hi->d,(void *)ni,code); ni+=size;
return 0;
case XDR_MEMORY:
default:
return 3*_xdr_int(NULL,NULL,XDR_MEMORY)+
_xdr_float(NULL,NULL,XDR_MEMORY)+
_xdr_double(NULL,NULL,XDR_MEMORY);
}
}
//-----------------------------------------------------------------------------
// Now the function to send a TEST structure becomes very simple !
// The following example returns 1 if success, 0 if a problem occurs.
// Binary conversion is automatically performed through the XDR routine
// written above.
// Warning : remember to call _rpc_flush() !
//-----------------------------------------------------------------------------
int _rpcsend_TEST (SOCKET Socket,
RPC_MSG *rpc_msg, XDR_BUFFER *xdr_buffer,
TEST *TestParameter)
{
return _rpcsend_buffer(Socket,rpc_msg,xdr_buffer,TestParameter,_xdr_TEST)==
_xdr_TEST(NULL,NULL,XDR_MEMORY);
}
//-----------------------------------------------------------------------------
// Similarly, the function to receive a TEST structure is also simple.
// Binary conversion is automatically performed through the XDR routine
// written above.
//-----------------------------------------------------------------------------
int _rpcrecv_TEST (SOCKET Socket,
XDR_BUFFER *xdr_buffer,
TEST *TestParameter)
{
return _rpcrecv_buffer(Socket,xdr_buffer,TestParameter,_xdr_TEST)==
_xdr_TEST(NULL,NULL,XDR_MEMORY);
}
//-----------------------------------------------------------------------------
// This is one of the most important functions : each time a message is
// received by the server, this function is called
// The first parameter rpc_func identifies the message
// The second parameter idClient identifies the client (the server can accept
// connections with multiple clients at the same time)
//-----------------------------------------------------------------------------
static void Dispatch (int rpc_func, int idClient)
{
SOCKET socket;
RPC_MSG *rpc_msg;
XDR_BUFFER *xdr_buffer;
char *client_buffer;
int I;
TEST Test;
// The first thing to do is to retrieve the parameters of the client
_GetClientInfo(idClient,
&socket,
&rpc_msg,
&xdr_buffer,
&client_buffer);
// Now, the function reduces to a big switch depending of the value of rpc_func
switch (rpc_func) {
// First kind of message (prefer constants defined by #define instead of numerical constants)
// This message requires to read additionnal parameters (int + TEST strcuture) from the socket
// The response of the server to the client : just add 1 to the int sent by the client, and then return it
// Similar changes to the TEST structure
// Note the call to _rpc_flush() !
case 1:
_rpcrecv_int(socket,xdr_buffer,&I);
_rpcrecv_TEST(socket,xdr_buffer,&Test);
printf("Data received from client : %d\n",I);
printf("TEST structure : %d %d %d %g %lg\n",Test.i1,Test.i2,Test.i3,Test.f,Test.d);
// Now change the values
I++;
Test.i1*=2;
Test.i2*=3;
Test.i3*=4;
Test.f=1.0f/Test.f;
Test.d=sqrt(Test.d);
// Now returns to changes parameters to client
_rpcsend_int(socket,rpc_msg,xdr_buffer,I);
_rpcsend_TEST(socket,rpc_msg,xdr_buffer,&Test);
_rpc_flush(socket,rpc_msg);
break;
// Other messages and associated code ...
default:
return;
}
}
//-----------------------------------------------------------------------------
// This accepts or not a connection from one client on the network, whose ip
// address is transmitted as a character string parameter. The return value is
// 0 (connection refused) or 1 (connection accepted)
//-----------------------------------------------------------------------------
static int AcceptConnection (char *ip)
{
return 1;
}
//-----------------------------------------------------------------------------
// This function is called each time a message is received on the udp socket
// of the server (if it exists).
// In this example, the server sends an answer made of one long int, followed
// by a 128 characters string.
//-----------------------------------------------------------------------------
void udpManager (SOCKET udpSocket)
{
sockaddr_in src_addr;
long int udpQuery;
int stat,len;
struct {
long int udpResponse;
char szb[128];
} udp;
// First I read the data from the udp socket. In this example, the client is assumed to send
// only a 32 bits message
len=sizeof(src_addr);
stat=recvfrom(udpSocket,(char *)&udpQuery,sizeof(long int),0,(struct sockaddr *)&src_addr,&len);
if (stat!=sizeof(long int)) return;
// Note the use of ntohl(), required by the XDR mechanism
udpQuery=ntohl(udpQuery);
// Depending on the received message, I generate the answer, replying (udpQuery+1)
switch (udpQuery) {
case 1:
udp.udpResponse=htonl(1+udpQuery); // response=query+1
strcpy(udp.szb,"udp query #1"); // text of the response
break;
default:
udp.udpResponse=htonl(0); // response=0
strcpy(udp.szb,""); // empty text
}
// Now send the response to the client who sent the udp request
sendto(udpSocket,(char *)&udp,sizeof(udp),MSG_DONTROUTE,(struct sockaddr *)&src_addr,sizeof(sockaddr_in));
}
//-----------------------------------------------------------------------------
// This function starts the server with a specific service
//-----------------------------------------------------------------------------
static void Start (char *service)
{
int stat;
SOCKET tcpSock